package com.app.backend.config.feign;

import com.fasterxml.jackson.annotation.JsonProperty;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;

/**
 * @author Jet Zheng
 */
@Slf4j
public class FeignObjectToFormEncoder implements Encoder {

    @Override
    public void encode(Object object, Type bodyType, RequestTemplate requestTemplate) throws EncodeException {
        try {
            String body = FieldUtils.getAllFieldsList(object.getClass()).stream().map(x -> {
                try {
                    Object value = FieldUtils.readField(x, object, true);
                    if (value == null) {
                        return null;
                    }
                    JsonProperty jsonProperty = x.getAnnotation(JsonProperty.class);
                    if (jsonProperty == null) {
                        return String.join("=", x.getName(), URLEncoder.encode(value.toString(), StandardCharsets.UTF_8.displayName()));
                    } else {
                        return String.join("=", jsonProperty.value(), URLEncoder.encode(value.toString(), StandardCharsets.UTF_8.displayName()));
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                }
                return null;
            }).filter(StringUtils::isNotBlank).collect(Collectors.joining("&"));

            requestTemplate.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
            requestTemplate.body(body);
        } catch (Exception e) {
            log.error("FeignFormEncoder.encode出错,错误原因:" + e);
            throw new RuntimeException("FeignFormEncoder.encode出错,错误原因:" + e);
        }
    }
}
